/*
 * Project name:
     CodexGUI

 * Version:  0.3
        1.0.0.10    -   File encryption, multiple entry display
 *      1.0.0.11    -   Rtf support implemented
 *                  -   Deleting of entries implemented
 *                  -   Entry updating interval changed from every keystroke to 
 *                      entry selection, new entry, and saving events to reduce lag
 *                  -   Save dialog added to exit
 *      1.0.1.0     -   Entries sorted by month & day in tree pane
 *                  -   Bold, Italic, Underline formatting and shortcut keys implemented
 *                  -   Text searching and highlighting implemented
 *                  -   Save dialog modified to be shown only when an entry has changed
 *               
 

 * Description:
     Manages the evaluation of individual neural nets and returns a fitness value for each one
 
 * Suggested improvements:  About box version display
                            GPS geotagging
                            Entry tagging
                            Sorting, searching
                            
 
 * Test configuration: 
 
 * Author: 
     Scott Nietfeld
*/

using System;
using System.Net.Mail;
using System.Net;
using Google.GData.Client;
using System.Text.RegularExpressions;

using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
using System.Security;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using System.Drawing.Printing;

namespace Codex
{
    public partial class CodexGUI : Form
    {
        private Codex currentCodex;
        private Entry selectedEntry;
        private bool entryChanged;
        private bool archiveChanged;
        private String fileName;
        private String backupFileName;
        private byte[] Key;
        private byte[] IV;
        private TimeSpan editCutoffSpan;
        private bool encrypted;
        private bool suppressRefresh;
        private int searchStart;
        private int highlightedStartIndex;
        private int highlightedLength;
        private Color highlightedColor;
        private Color highlightedBackColor;
        

        public CodexGUI()
        {
            editCutoffSpan = TimeSpan.FromHours(12.0);
            backupFileName = "backup.dex";
            encrypted = false;
            suppressRefresh = false;

            InitializeComponent();

            entryTextBox.Enabled = false;
            findTextBox.Visible = false;

            this.Show();
            this.Location = Properties.Settings.Default.formLocation;
            this.Size = new Size(Properties.Settings.Default.formWidth,
                Properties.Settings.Default.formHeight);
            

            Console.WriteLine("Setting size: " +
                Properties.Settings.Default.formWidth + "x" +
                Properties.Settings.Default.formHeight);
            Console.WriteLine(Properties.Settings.Default.lastSaveDirectory);

            
            //If the last saved directory cannot be found
            if (!System.IO.Directory.Exists(Properties.Settings.Default.lastSaveDirectory))
            {
                //Set default directory to current workign directory
                Properties.Settings.Default.lastSaveDirectory = System.IO.Directory.GetCurrentDirectory();
                Console.WriteLine(Properties.Settings.Default.lastSaveDirectory);

                System.Windows.Forms.MessageBox.Show("Default directory: " +
                        Properties.Settings.Default.lastSaveDirectory +
                        "\nCould not be found.");

                Properties.Settings.Default.ArchiveFilename = "";
            }
            else
            {
                System.IO.Directory.SetCurrentDirectory(
                    Properties.Settings.Default.lastSaveDirectory);
            }

            //Debug: Console.WriteLine("Default: " + Properties.Settings.Default.ArchiveFilename);

            if (System.IO.File.Exists(Properties.Settings.Default.ArchiveFilename))
            {
                fileName = Properties.Settings.Default.ArchiveFilename;

                try
                {
                    openCodex(fileName);
                }
                catch (Exception ex) 
                {
                    System.Windows.Forms.MessageBox.Show("Default archive: "
                        + Properties.Settings.Default.ArchiveFilename
                        + "could not be found.");
                    //Console.WriteLine("Could not open default archive."); 
                }
                    //Console.WriteLine("Running main method...");
            }

            fieldNameCol.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
            fieldGrid.Rows.Clear();
            fieldGrid.Columns[1].ReadOnly = false;

            setFontRegular();
            //refreshFont();

            timer1.Start();
        }


        private void refreshLabelList()
        {
            string tempTag = "";

            if (tagListBox.SelectedItem != null) 
                tempTag = tagListBox.SelectedItem.ToString();
            
            tagListBox.Items.Clear();

            //Get all tags used in codex and add to label list box
            foreach (String label in currentCodex.getAllLabels())
            {
                tagListBox.Items.Add(label);
            }

            if (selectedEntry != null)
            {
                for(int i = 0; i < tagListBox.Items.Count; i++)
                {
                    Object tag = tagListBox.Items[i];

                    Console.Out.WriteLine("Tag tostring: " + tag.ToString());
                    if (selectedEntry.hasLabel(tag.ToString()))
                    {
                        tagListBox.SetItemCheckState(i, CheckState.Checked);
                    }
                    else tagListBox.SetItemCheckState(i, CheckState.Unchecked);
                }
                tagListBox.ClearSelected();
            }

            if (tagListBox.Items.Contains(tempTag)) tagListBox.SelectedItem = tempTag;
        }

        private void richTextBox1_TextChanged(object sender, EventArgs e)
        {
            try
            {
                if (selectedEntry != null)
                {
                    //Debug:Console.Write("Changing :\n" + selectedEntry.getEntryText() +
                        //Debug:"\nTo:\n" + richTextBox1.Rtf);
                    archiveChanged = true;
                    entryChanged = true;
                    //selectedEntry.setEntryText(richTextBox1.Rtf);
                    //Console.WriteLine("Setting entry text...");
                }
            }
            catch (Exception ex) { statusStrip1.Text = "Error: No selected entry"; }
        }

        private void splitContainer1_Panel1_Paint(object sender, PaintEventArgs e)
        {
            //refresh();
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Save currently selected treeNode
            
            /* Trick the fieldGrid into committing the value of any cell currently
             * being edited.*/
            fieldGrid.Enabled = false;
            fieldGrid.Enabled = true;
            commitFieldCellChanges();

            //If currently selected entry has been changed, save it
            if (entryChanged == true)
            {
                selectedEntry.setEntryText(entryTextBox.Rtf);
                entryChanged = false;
                Console.WriteLine("Setting entry text...");
            }

            saveCodex();

            archiveChanged = false;
        }

        private void getPassword()
        {
            String password = InputBox.Show("Password:", "");

            if (password.Equals(""))
            {
                encrypted = false;
            }
            else
            {
                encrypted = true;

                if (password.Length > 16) password = password.Substring(0, 16);
                else password = password.PadRight(16);

                //Debug: Console.WriteLine(password);
            }
            

            Key = ASCIIEncoding.ASCII.GetBytes(password);
            IV = ASCIIEncoding.ASCII.GetBytes(password);
        }

        private void openCodex()
        {
            if (openFileDialog1.ShowDialog() != DialogResult.OK) return;

            fileName = openFileDialog1.FileName;

            openCodex(fileName);

            if (currentCodex.entryList.Count > 0)
            {
                treeView1.SelectedNode = treeView1.Nodes[treeView1.Nodes.Count - 1];

                refreshLabelList();
            }
        }

        private void openCodex(string _fileName)
        {
            //Do some filename checking
            Console.WriteLine(_fileName);
            if(_fileName.Contains(".") && !_fileName.EndsWith(".dex"))
            {
                System.Windows.Forms.MessageBox.Show("Not a valid .dex file.");
                return;
            }
            else if(!_fileName.Contains("."))
            {
                _fileName += ".dex";
            }
            
            
            //Try to deserialize without decrypting
            currentCodex = deserializeCodex(_fileName);

            if (currentCodex == null)
            {
                encrypted = true;
                getPassword();
                currentCodex = decryptCodexFromFile(fileName, Key, IV);
            }
            else encrypted = false;

            //If the opened file is still no good, inform user
            if (currentCodex == null) System.Windows.Forms.MessageBox.Show(
                "Corrupt file or incorrect password");
            else
            {
                //Set the default archive to the one being opened
                if (!_fileName.Equals(Properties.Settings.Default.ArchiveFilename))
                    Properties.Settings.Default.ArchiveFilename = _fileName;

                backupFileName = _fileName.Split('.')[0] + 
                    backupFileName;
                try
                {
                    if(System.IO.File.Exists(backupFileName))
                    {
                        System.IO.File.Delete(backupFileName);
                        System.IO.File.Copy(_fileName, backupFileName);
                    }
                    else 
                    {
                        //System.IO.File.Create(backupFileName);
                        System.IO.File.Copy(_fileName, backupFileName, true);
                    }
                }
                catch (Exception e)
                {
                    System.Windows.Forms.MessageBox.Show(
                        "WARNING: Backup file could not be created.");
                }
            }

            //Convert all non-rtf entries to rtf for backward-compatibility
            if (currentCodex != null) convertAllToRTF(currentCodex);

            entryTextBox.Clear();
            treeView1.Nodes.Clear();
            entryTextBox.Enabled = true;
            refresh();
            //Console.Write(currentCodex.ToString())
        }

        private void convertAllToRTF(Codex tempCodex)
        {
            if (currentCodex.entryList.Count == 0) return;

            //If entries have already been converted, return
            if(isRTF(tempCodex.entryList[0].getEntryText())) return;

            foreach (Entry tempEntry in tempCodex.getEntryList())
            {
                tempEntry.setEntryText(convertToRTF(tempEntry.getEntryText()));
            }
        }

        private string convertToRTF(string textString)
        {
            if(isRTF(textString))
            {
                return textString;
            }
            else
            {
                RichTextBox temprtb = new RichTextBox();
                temprtb.Font = Properties.Settings.Default.TextPaneFont;
                temprtb.ForeColor = Properties.Settings.Default.TextPaneFontColor;
                temprtb.Text = textString;
                return temprtb.Rtf;
            }
        }

        public string appendTextToRTF(string rtf, string text)
        {
            rtf.Insert(rtf.Length - 3, text);

            return rtf;
        }

        private string concatenateRTF(string string1, string string2)
        {
            if (string1.Equals("")) return string2;
            else if (string2.Equals("")) return string1;


            string finalRTF = "";

            try
            {
                Console.WriteLine("String1: " + string1 + "\nString2: " + string2);
                finalRTF = getRTFHeader(string1);
                Console.WriteLine(finalRTF);
                finalRTF += stripRtf(string1);
                Console.WriteLine(finalRTF);
                finalRTF += stripRtf(string2);
                Console.WriteLine(finalRTF);
                finalRTF += getRTFFooter(string2);
            }
            catch (Exception) { return convertToRTF(""); }

            Console.WriteLine(finalRTF);

            return finalRTF;
        }


        private string getRTFHeader(string rtfString)
        {

            int headerEndIndex = rtfString.IndexOf("{\\font");
            //Console.WriteLine("Header end: " + rtfString.IndexOf("{\\fonttbl"));
            //Console.WriteLine("Before: " + rtfString);
            //Console.WriteLine("After: " + rtfString.Remove(headerEndIndex));

            return rtfString.Remove(headerEndIndex);
        }

        private string getRTFFooter(string rtfString)
        {
            //return rtfString.Substring(rtfString.LastIndexOf('}'),
            //    rtfString.Length - rtfString.LastIndexOf('}'));

            return rtfString.Substring(rtfString.Length - 3, 3);
        }

        private string stripRtf(String text)
        {
            int startIndex = text.IndexOf("{\\fonttbl");
            int endIndex = text.LastIndexOf('}') - 1;

            string rtfString = text.Substring(startIndex, endIndex - startIndex)
                + "\n";

            //Console.WriteLine("\n\n\n" + rtfString);

            return rtfString;
        }

        private bool isRTF(string testString)
        {
            if(testString.StartsWith("{\\rtf"))
                return true;
            else return false;
        }

        private void saveCodex()
        {
            if (currentCodex == null)
            {
                currentCodex = new Codex();
            }

            if (fileName == null)
            {
                saveFileDialog1.ShowDialog();
                if (saveFileDialog1.FileName.Equals(""))
                {
                    System.Windows.Forms.MessageBox.Show("File was not saved.");
                    return;
                }
                else
                    fileName = saveFileDialog1.FileName;
            }

            Console.WriteLine("Saving file...");

            if (encrypted == true)
                encryptCodexToFile(currentCodex, fileName, Key, IV);
            else serializeCodex(fileName, currentCodex);

            //Save default settings....
            Properties.Settings.Default.ArchiveFilename = fileName;
            Properties.Settings.Default.lastSaveDirectory = System.IO.Directory.GetCurrentDirectory();

            refresh();
        }

        public static Codex deserializeCodex(String FileName)
        {
            try
            {
                Codex tempCodex = null;

                // Create or open the specified file. 
                FileStream fStream = File.Open(FileName, FileMode.OpenOrCreate);

                // Create a StreamReader using the CryptoStream.
                StreamReader sReader = new StreamReader(fStream);

                XmlSerializer serializer = new XmlSerializer(typeof(Codex));


                try
                {
                    // Read the data from the stream 
                    // to decrypt it.
                    tempCodex = (Codex)serializer.Deserialize(sReader);

                }
                catch (Exception e)
                {
                    Console.WriteLine("An error occurred: {0}", e.Message);
                }
                finally
                {

                    // Close the streams and
                    // close the file.
                    sReader.Close();
                    fStream.Close();
                }

                // Return the string. 
                return tempCodex;
            }
            catch (CryptographicException e)
            {
                Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
                Console.WriteLine(e.ToString());
                return null;
            }
            catch (UnauthorizedAccessException e)
            {
                Console.WriteLine("A file error occurred: {0}", e.Message);
                return null;
            }
        }

        public void serializeCodex(String FileName, Codex tempCodex)
        {
            try
            {
                //Delete original file
                System.IO.File.Delete(FileName);

                // Create or open the specified file.
                FileStream fStream = File.Open(FileName, FileMode.OpenOrCreate);


                // Create a StreamWriter using the CryptoStream.
                TextWriter sWriter = new StreamWriter(fStream);

                XmlSerializer serializer = new XmlSerializer(typeof(Codex));
                
                try
                {
                    // Write the data to the stream 
                    // to encrypt it.
                    //sWriter.WriteLine(Data);
                    serializer.Serialize(sWriter, tempCodex);
                }
                //If any error occurred during the process
                catch (Exception e)
                {
                    Console.WriteLine("An error occurred: {0}", e.Message);
                }
                finally
                {
                    // Close the streams and
                    // close the file.
                    sWriter.Close();
                    fStream.Close();
                }
            }
            catch (UnauthorizedAccessException e)
            {
                Console.WriteLine("A file error occurred: {0}", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);

                System.Windows.Forms.MessageBox.Show(
                    "An error occured while saving." +
                    "The current codex has been backed up to: " + backupFileName);
            }
        }

        public static Codex decryptCodexFromFile(String FileName, byte[] Key, byte[] IV)
        {
            try
            {
                Codex tempCodex = null;

                // Create or open the specified file. 
                FileStream fStream = File.Open(FileName, FileMode.OpenOrCreate);

                // Create a new Rijndael object.
                Rijndael RijndaelAlg = Rijndael.Create();
                RijndaelAlg.Padding = PaddingMode.Zeros;

                // Create a CryptoStream using the FileStream 
                // and the passed key and initialization vector (IV).
                CryptoStream cStream = new CryptoStream(fStream,
                    RijndaelAlg.CreateDecryptor(Key, IV),
                    CryptoStreamMode.Read);

                // Create a StreamReader using the CryptoStream.
                StreamReader sReader = new StreamReader(cStream);

                XmlSerializer serializer = new XmlSerializer(typeof(Codex));


                try
                {
                    // Read the data from the stream 
                    // to decrypt it.
                    tempCodex = (Codex)serializer.Deserialize(sReader);
                }
                catch (Exception e)
                {
                    Console.WriteLine("An error occurred: {0}", e.Message);

                    
                    //Ask use if they want to save decrypted text
                    DialogResult dlgResult;
                    dlgResult = MessageBox.Show("File may be corrupted. Save decrypted text?", "Codex",
                    MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation);

                    if (dlgResult == DialogResult.Yes)
                    {
                        SaveFileDialog saveFileDialog1 = new SaveFileDialog();
                        saveFileDialog1.CheckFileExists = false;

                        //Save decrypted contents to file
                        if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                        {
                            string dumpPath = saveFileDialog1.FileName;

                            string fileString = sReader.ReadToEnd();

                            StreamWriter writer = new StreamWriter(dumpPath);
                            writer.Write(fileString);
                            writer.Flush();
                            writer.Close();
                            MessageBox.Show("Decrypted text saved to " + dumpPath);
                        }
                    }
                }
                finally
                {
                    // Close the streams and
                    // close the file.
                    sReader.Close();
                    cStream.Close();
                    fStream.Close();
                }

                // Return the string. 
                return tempCodex;
            }
            catch (CryptographicException e)
            {
                Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
                Console.WriteLine(e.ToString());
                return null;
            }
            catch (UnauthorizedAccessException e)
            {
                Console.WriteLine("A file error occurred: {0}", e.Message);
                return null;
            }
        }

        public static void encryptCodexToFile(Codex tempCodex, String FileName, byte[] Key, byte[] IV)
        {
            try
            {
                // Create or open the specified file.
                FileStream fStream = File.Open(FileName, FileMode.OpenOrCreate);

                // Create a new Rijndael object.
                Rijndael RijndaelAlg = Rijndael.Create();
                RijndaelAlg.Padding = PaddingMode.Zeros;

                // Create a CryptoStream using the FileStream 
                // and the passed key and initialization vector (IV).
                CryptoStream cStream = new CryptoStream(fStream,
                    RijndaelAlg.CreateEncryptor(Key, IV),
                    CryptoStreamMode.Write);

                // Create a StreamWriter using the CryptoStream.
                TextWriter sWriter = new StreamWriter(cStream);

                XmlSerializer serializer = new XmlSerializer(typeof(Codex));
                try
                {
                    // Write the data to the stream 
                    // to encrypt it.
                    //sWriter.WriteLine(Data);
                    serializer.Serialize(sWriter, tempCodex);
                }
                catch (Exception e)
                {
                    Console.WriteLine("An error occurred: {0}", e.Message);
                }
                finally
                {
                    // Close the streams and
                    // close the file.
                    sWriter.Close();
                    cStream.Close();
                    fStream.Close();
                }
            }
            catch (CryptographicException e)
            {
                Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
            }
            catch (UnauthorizedAccessException e)
            {
                Console.WriteLine("A file error occurred: {0}", e.Message);
            }

        }

        private void createNewArchive()
        {
            if(saveFileDialog1.ShowDialog() != DialogResult.OK) return;


            selectedEntry = null;
            currentCodex = null;
            tagListBox.Items.Clear();
            treeView1.Nodes.Clear();
            entryTextBox.Clear();
            
            fileName = saveFileDialog1.FileName;

            //Do some filename checking
            if (fileName.Contains(".") && !fileName.EndsWith(".dex"))
            {
                //System.Windows.Forms.MessageBox.Show("Not a valid .dex file.");
                fileName = fileName.Split('.')[0] + ".dex";
                return;
            }
            else if (!fileName.Contains("."))
            {
                fileName += ".dex";
            }

            currentCodex = new Codex();

            getPassword();

            saveCodex();

            openCodex(fileName);
        }

        private void refresh()
        {
            if (currentCodex == null) return;
            if (suppressRefresh == true) return;

            TreeNode tempNode;
            TreeNode tempNode2;
            TreeNode newEntryNode;

            currentCodex.sortByDate();

            treeView1.Nodes.Clear();

            //Old code for sorting by year only
            //foreach (int tempYear in getYearList(currentCodex))
            //{
            //    TreeNode tempYearNode = new TreeNode(tempYear.ToString());
            //    tempYearNode.Name = "#year:" + tempYearNode.Text;
            //    treeView1.Nodes.Add(tempYearNode);

            //    foreach (Entry tempEntry in currentCodex.getEntryList())
            //    {
            //        newEntryNode = new TreeNode(tempEntry.getEntryDate().ToString());
            //        newEntryNode.Name = newEntryNode.Text;

            //        if (tempEntry.getEntryDate().Year == tempYear)
            //            tempYearNode.Nodes.Add(newEntryNode);
            //    }
            //}

            //New code for sorting by year,month,day
            DateTime tempDate = new DateTime();
            foreach (Entry tempEntry in currentCodex.getEntryList())
            {
                tempDate = tempEntry.getEntryDate();

                //If tree doesn't contain node for year, create it
                if (!treeView1.Nodes.ContainsKey("#year:" + tempDate.Year.ToString()))
                {
                    tempNode = new TreeNode(tempDate.Year.ToString());
                    tempNode.Name = "#year:" + tempDate.Year.ToString();
                    treeView1.Nodes.Add(tempNode);
                }

                //Set the temp node to the corresponding year node
                tempNode = treeView1.Nodes[treeView1.Nodes.IndexOfKey(
                    "#year:" + tempDate.Year.ToString())];
            
                //If year node doesn't contain month node, create it
                if (!tempNode.Nodes.ContainsKey("#month:" + tempDate.ToString("MMMM")))
                {
                    tempNode2 = new TreeNode(tempDate.ToString("MMMM"));
                    tempNode2.Name = "#month:" + tempDate.ToString("MMMM");
                    tempNode.Nodes.Add(tempNode2);
                }

                //Set the temp node to the corresponding month node
                tempNode = tempNode.Nodes[tempNode.Nodes.IndexOfKey(
                    "#month:" + tempDate.ToString("MMMM"))];
            
                //If month node doesn't contain day node, create it
                if (!tempNode.Nodes.ContainsKey("#day:" + tempDate.Day.ToString()))
                {
                    tempNode2 = new TreeNode(tempDate.Day.ToString());
                    tempNode2.Name = "#day:" + tempDate.Day.ToString();
                    tempNode.Nodes.Add(tempNode2);
                }


                //Find correct day node and add new entry node to it
                newEntryNode = new TreeNode(tempDate.ToString());
                newEntryNode.Name = "#entry:" + tempDate.ToString();

                tempNode = treeView1.Nodes[treeView1.Nodes.IndexOfKey(
                    "#year:" + tempDate.Year.ToString())];

                tempNode = tempNode.Nodes[tempNode.Nodes.IndexOfKey(
                    "#month:" + tempDate.ToString("MMMM"))];

                tempNode = tempNode.Nodes[tempNode.Nodes.IndexOfKey(
                    "#day:" + tempDate.Day.ToString())];

                tempNode.Nodes.Add(newEntryNode);
            }

            treeView1.ExpandAll();

            this.Text = "Codex     " + fileName;

            refreshFieldGrid();
        }

        private void refreshTree(TreeNode selectedNode)
        {
            //Console.WriteLine("Refreshing tree...");
            //Console.WriteLine("Start of refreshTree" +DateTime.Now.ToString() + ":" + DateTime.Now.Millisecond.ToString());
            TreeNode originalNode = selectedNode;

            //Make selected entry null so clear won't overwrite contents
            selectedEntry = null;
            entryTextBox.Clear();

            updateSelectedEntry(selectedNode);

            //Try to read nodeText as rtf-formatted
            try
            {
                //richTextBox1.Text += getNodeText(selectedNode);
                entryTextBox.Rtf = selectedEntry.getEntryText();
            }
            //If the nodeText isn't formatted as rtf, just print it as plaintext
            catch (Exception ex)
            {
                entryTextBox.Text = getNodeText(selectedNode);
            }

            if (selectedNode.NextVisibleNode == null)
            {
                updateReadOnly();
                return;
            }


            int startLevel = selectedNode.Level;

            RichTextBox temprtb = new RichTextBox();
            temprtb.Font = Properties.Settings.Default.TextPaneFont;
            temprtb.ForeColor = Properties.Settings.Default.TextPaneFontColor;

            TreeNode tempNode = selectedNode.NextVisibleNode;

            Console.WriteLine("Start of while: " + DateTime.Now.ToString() + ":" + DateTime.Now.Millisecond.ToString());
            //This code excecutes only for nodes with subnodes (categories)
            while (tempNode.Level > startLevel)
            {
                //Console.WriteLine("Top of while: " + DateTime.Now.ToString() + ":" + DateTime.Now.Millisecond.ToString());
            
                entryTextBox.ReadOnly = false;
                //richTextBox1.Rtf = appendTextToRTF(richTextBox1.Rtf, "\\par\\par\\par");

                //Move caret to end of text box
                entryTextBox.Select(entryTextBox.Rtf.Length, 0);
                //Copy new text into fake text box
                temprtb.Clear();
                temprtb.Rtf = convertToRTF("\n\n\n" + tempNode.Text + "\n\n");
                temprtb.SelectAll();
                temprtb.Copy();
                entryTextBox.Paste();

                //Console.WriteLine("After title paste: " + DateTime.Now.ToString() + ":" + DateTime.Now.Millisecond.ToString());
            
                if (tempNode.Name.StartsWith("#entry:"))
                {
                    temprtb.Clear();

                    /*String entryText = getNodeText(tempNode)

                    if(entryText.Contains("{\\pict\\"))
                    {
                        
                    }
                    else
                    {*/
                        temprtb.Rtf = convertToRTF(getNodeText(tempNode));
                    
                    temprtb.AppendText("\n\n");
                    temprtb.SelectAll();
                    temprtb.Copy();
                    entryTextBox.Paste();

                    //Console.WriteLine("After text paste: " + DateTime.Now.ToString() + ":" + DateTime.Now.Millisecond.ToString());
                 

                    //richTextBox1.Rtf = appendTextToRTF(richTextBox1.Rtf, "\\par\\par");
                    //Console.WriteLine("After appendRTF: " + DateTime.Now.ToString() + ":" + DateTime.Now.Millisecond.ToString());
                 
                }
                           

                tempNode = tempNode.NextVisibleNode;
                if (tempNode == null) break;
            }
            //Console.WriteLine("End of while: " + DateTime.Now.ToString() + ":" + DateTime.Now.Millisecond.ToString());
            updateSelectedEntry(originalNode);
            updateReadOnly();
            setFontRegular();

            return;
        }

        

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            openCodex();
        }

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            Console.WriteLine("Name/Key: " + treeView1.SelectedNode.Name);

            if (entryChanged == true)
            {
                selectedEntry.setEntryText(entryTextBox.Rtf);
                entryChanged = false;
                Console.WriteLine("Setting entry text...");
            }

            refreshTree(e.Node);
            refreshLabelList();
            refreshFieldGrid();
            if (treeView1.SelectedNode.Name.StartsWith("#entry"))
            {
                tagListBox.Enabled = true;
                fieldGrid.Enabled = true;
            }
            else
            {
                tagListBox.Enabled = false;
                fieldGrid.Enabled = false;
            }
        }

        private string getNodeText(TreeNode tempNode)
        {
            DateTime selectedDate;
            Entry tempEntry;

            if (DateTime.TryParse(tempNode.Text, out selectedDate))
            {
                selectedDate = DateTime.Parse(tempNode.Text);
                //Console.WriteLine("Selected Date: " + selectedDate.ToString());

                try
                {
                    tempEntry = currentCodex.getEntry(selectedDate);
                    //Console.WriteLine("Entry Text: " + tempEntry.getEntryText());
                }
                catch (Exception ex) { return ""; }

                return tempEntry.getEntryText();
            }
            else
            {
                selectedEntry = null;
                //Debug:Console.WriteLine("selectedEntry = null");
                return tempNode.Text + "\n\n";
            }
        }

        private void updateReadOnly()
        {
            if (selectedEntry == null)
            {
                entryTextBox.ReadOnly = true;
                return;
            }

            DateTime selectedDate = selectedEntry.getEntryDate();

            //If selected entry was made more than editCutoffHours hours ago, disable editing
            TimeSpan timeSinceEntry = DateTime.Now.Subtract(selectedDate).Duration();
            if (timeSinceEntry > editCutoffSpan) entryTextBox.ReadOnly = true;
            else entryTextBox.ReadOnly = false;
            return;
        }

        private void updateSelectedEntry(TreeNode selectedNode)
        {
            try
            {
                selectedEntry = currentCodex.getEntry(DateTime.Parse(selectedNode.Text));
            }
            catch (Exception ex) { selectedEntry = null; }

            return;
        }
        
       

        private void entryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //If currently selected entry has been changed, save it
            if (entryChanged == true)
            {
                if(selectedEntry != null)
                    selectedEntry.setEntryText(entryTextBox.Rtf);
                entryChanged = false;
                Console.WriteLine("Setting entry text...");
            }

            selectedEntry = null;

            //If no archive is open, create a new one
            if (currentCodex == null)
            {
                createNewArchive();
                return;
            }

            entryTextBox.Enabled = true;
            entryTextBox.ReadOnly = false;
            entryTextBox.Clear();
            entryTextBox.Focus();
            setFontRegular();

            createNewEntry(dateTimePicker1.Value, "");
        }


              
        private void createNewEntry(DateTime newEntryDate, string newEntryText)
        {
            //If currently selected entry has been changed, save it
            if (entryChanged == true)
            {
                selectedEntry.setEntryText(entryTextBox.Rtf);
                entryChanged = false;
                Console.WriteLine("Setting entry text...");
            }
            
            Entry newEntry = new Entry(newEntryDate, newEntryText);
            try
            {
                currentCodex.addEntry(newEntry);
            }
            catch (Exception ex)
            {
                statusLabel.Text = "Cannot create new entry. No codex open.";
                return;
            }

            if (currentCodex.entryList.Count > 1)
            {
                newEntry.setLabelList(currentCodex.entryList[currentCodex.entryList.Count - 2].getLabelList());
            }

            foreach (string fieldName in currentCodex.getAllFieldNames())
            {
                newEntry.addField(fieldName);
            }

            refresh();
            selectedEntry = newEntry;
            treeView1.SelectedNode = treeView1.Nodes.Find("#entry:" + newEntryDate.ToString(), true)[0];
            refreshLabelList();
            setFontRegular();
        }

        private TreeNode findNode(DateTime date)
        {
            foreach (TreeNode tempNode in treeView1.Nodes)
            {
                if (tempNode.Text.Equals(date.ToString())) return tempNode;
            }
            throw new FieldAccessException();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            dateTimePicker1.Value = DateTime.Now;
            dateTimePicker1.Text = dateTimePicker1.Value.ToString();
        }

        private void printToolStripMenuItem_Click(object sender, EventArgs e)
        {
            printDocument1.Print();
        }

        private void printPreviewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            printPreviewDialog1.ShowDialog();
        }

        private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            AboutBox1 aboutBox = new AboutBox1();
            aboutBox.Show();
        }

        private List<int> getYearList(Codex tempCodex)
        {
            List<int> yearList = new List<int>();

            foreach (Entry tempEntry in tempCodex.getEntryList())
            {
                if (!yearList.Contains(tempEntry.getEntryDate().Year))
                    yearList.Add(tempEntry.getEntryDate().Year);
            }
            return yearList;
        }

        private void CodexGUI_FormClosing(object sender, FormClosingEventArgs e)
        {
            //If nothing has been changed, just exit
            if (archiveChanged == false) return;

            //Ask use if they want to save
            DialogResult dlgResult;
            dlgResult = MessageBox.Show("Save current codex?", "Codex",
                MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation);

            if (dlgResult == DialogResult.No)
            {
                return;
            }
            else if (dlgResult == DialogResult.Yes)
            {
                //user chose 'yes', save current document
                //If currently selected entry has been changed, save it
                if (entryChanged == true)
                {
                    selectedEntry.setEntryText(entryTextBox.Rtf);
                    entryChanged = false;
                    Console.WriteLine("Setting entry text...");
                }

                saveCodex();

                //Save default settings
                Properties.Settings.Default.Save();

                return;
            }
            //else if user chose 'cancel' do nothing
            e.Cancel = true;

            return; //document not closed
        }

        private void optionsToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            OptionsForm opForm = new OptionsForm();
            opForm.Visible = true;
        }

        private void dateTimePicker1_DropDown(object sender, EventArgs e)
        {
            timer1.Stop();
        }

        private void archiveToolStripMenuItem2_Click(object sender, EventArgs e)
        {
            createNewArchive();
        }

        private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            entryTextBox.Paste();
        }

        private void setChangePasswordToolStripMenuItem_Click(object sender, EventArgs e)
        {
            getPassword();
        }

        private void saveAsToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if(saveFileDialog1.ShowDialog() != DialogResult.OK) return;
            
            fileName = saveFileDialog1.FileName;

            saveCodex();
        }

        private void deleteToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            try
            {
                deleteEntry(DateTime.Parse(treeView1.SelectedNode.Text));
            }
            catch (Exception ex) { }
        }

        private void deleteEntry(DateTime selectedDate)
        {
            entryChanged = false; //Keep from trying to save changes
            updateSelectedEntry(treeView1.SelectedNode);
            currentCodex.removeEntry(selectedEntry);
            refresh();
            refreshTree(treeView1.SelectedNode);
        }

        private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            treeView1.SelectedNode = e.Node;
        }

        private void exitToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            this.Close();
        }



        /*--------------------------------------------------------------------------*
         *                                Font Methods                              *
         * -------------------------------------------------------------------------*/
        private void setFontRegular()
        {
            if (entryTextBox.SelectionFont.Bold) toggleBoldFont();
            if (entryTextBox.SelectionFont.Italic) toggleItalicFont();
            if (entryTextBox.SelectionFont.Underline) toggleUndFont();
        }
        
        private void toggleBoldFont(object sender, EventArgs e) { toggleBoldFont(); }
        private void toggleBoldFont()
        {
            Font newFont;

            if (entryTextBox.SelectionFont.Bold)
            {
                newFont = new Font(entryTextBox.Font,
                    entryTextBox.SelectionFont.Style ^ FontStyle.Bold);
            }
            else
            {
                newFont = new Font(entryTextBox.Font, 
                    entryTextBox.SelectionFont.Style | FontStyle.Bold);
            }
            //boldToolStripButton.Checked = !boldToolStripButton.Checked;
            entryTextBox.SelectionFont = newFont;
            //refreshFont();
        }

        private void toggleItalicFont(object sender, EventArgs e) { toggleItalicFont(); }
        private void toggleItalicFont()
        {
            Font newFont;

            if (entryTextBox.SelectionFont.Italic)
            {
                newFont = new Font(entryTextBox.Font,
                    entryTextBox.SelectionFont.Style ^ FontStyle.Italic);
            }
            else
            {
                newFont = new Font(entryTextBox.Font,
                    entryTextBox.SelectionFont.Style | FontStyle.Italic);
            }
            //italicToolStripButton.Checked = !italicToolStripButton.Checked;
            entryTextBox.SelectionFont = newFont;
            //refreshFont();
        }

        private void toggleUndFont(object sender, EventArgs e) { toggleUndFont(); }
        private void toggleUndFont()
        {
            Font newFont;

            if (entryTextBox.SelectionFont.Underline)
            {
                newFont = new Font(entryTextBox.Font,
                    entryTextBox.SelectionFont.Style ^ FontStyle.Underline);
            }
            else
            {
                newFont = new Font(entryTextBox.Font,
                    entryTextBox.SelectionFont.Style | FontStyle.Underline);
            }
            //undToolStripButton.Checked = !undToolStripButton.Checked;
            entryTextBox.SelectionFont = newFont;
            //refreshFont();
        }

        private void refreshFont(object sender, EventArgs e){ refreshFont(); }
        private void refreshFont()
        {
            Console.Out.WriteLine("Running refreshFont()");
            try
            {
                //boldToolStripButton.Checked = richTextBox1.SelectionFont.Bold;
                //italicToolStripMenuItem.Checked = richTextBox1.SelectionFont.Italic;
                //underlineToolStripMenuItem.Checked = richTextBox1.SelectionFont.Underline;
            }
            catch (Exception ex) { }
        }

        private void find(object sender, EventArgs e) { find(); }
        private void find()
        {
            searchStart = entryTextBox.SelectionStart;

            findTextBox.Visible = true;
            findTextBox.Select();
        }

        private void findTextBox_Leave(object sender, EventArgs e)
        {
            clearHighlight();
            findTextBox.Visible = false;
            findTextBox.Clear();
        }

        //private void findTextBox_TextChanged(object sender, EventArgs e)
        //{
        //    if (findTextBox.Text.Equals("")) return;

        //    int findIndex = 
        //        richTextBox1.Find(findTextBox.Text, richTextBox1.SelectionStart, RichTextBoxFinds.None);

        //    if (findIndex > 0)
        //    {
        //        richTextBox1.Select(findIndex, findTextBox.Text.Length);
        //    }
        //}

        private void findTextBox_TextChanged(object sender, EventArgs e)
        {
            findNext();
        }

        private void findNext()
        {
            clearHighlight();

            entryTextBox.Select(searchStart, 0);

            suppressRefresh = true;

            string text = findTextBox.Text;
            int start = entryTextBox.SelectionStart;

            // Initialize the return value to false by default.
            int returnValue = -1;

            // Ensure that a search string has been specified and a valid start point.
            if (text.Length > 0 && start >= 0)
            {
                // Obtain the location of the search string in richTextBox1.
                highlightedStartIndex = entryTextBox.Find(text, start, RichTextBoxFinds.None);

                if (highlightedStartIndex <= 0) return;
                
                highlightedLength = text.Length;

                entryTextBox.Select(highlightedStartIndex, highlightedLength);
                highlightedColor = entryTextBox.SelectionColor;
                highlightedBackColor = entryTextBox.SelectionBackColor;

                entryTextBox.SelectionBackColor = Color.Blue;
                entryTextBox.SelectionColor = Color.White;

                entryTextBox.ScrollToCaret();

                entryTextBox.Select(searchStart, 0);
            }

            suppressRefresh = false;
            return;
        }

        private void clearHighlight()
        {
            try
            {
                entryTextBox.Select(highlightedStartIndex, highlightedLength);
            }
            catch (Exception ex) { }
            entryTextBox.SelectionColor = highlightedColor;
            entryTextBox.SelectionBackColor = highlightedBackColor;
        }

        private void findTextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyValue == 13)
            {
                searchStart = highlightedStartIndex + highlightedLength;
                findNext();
            }
        }

        private void postBtn_Click(object sender, EventArgs e)
        {
            if(Properties.Settings.Default.blogAuthName.Equals("-empty-"))
            {
                OptionsForm opForm = new OptionsForm();
                opForm.Show();
                return;
            }
            
            statusLabel.Text = "Posting entry to blag...";
            Refresh();

            String userName = Properties.Settings.Default.blogUserName;
            String password = Properties.Settings.Default.blogPassword;

            Service service = new Service("blogger", "codex");
            service.Credentials = new GDataCredentials(userName, password);

            AtomEntry newPost = new AtomEntry();

            newPost.Title.Text = "";
            foreach (FieldTag tempField in selectedEntry.getFieldList())
            {
                if (tempField.getFieldName().ToLower().Equals("title"))
                    newPost.Title.Text = tempField.getFieldValue();
            }
            if(newPost.Title.Text.Equals(""))
                newPost.Title.Text = InputBox.Show("Post title:", "");

            
            foreach (string label in selectedEntry.getLabelList())
            {
                AtomCategory category = new AtomCategory();
                category.Scheme = "http://www.blogger.com/atom/ns#";
                category.Term = label;
                newPost.Categories.Add(category);
            }

            newPost.Published = selectedEntry.getEntryDate();

            newPost.Content = new AtomContent();


            if (entryTextBox.SelectedText.Length > 1)
                newPost.Content.Content = 
                    insertHTMLCodes(entryTextBox.SelectedText);
            else
                newPost.Content.Content = 
                    insertHTMLCodes(entryTextBox.Text);

            newPost.Content.Type = "xhtml";
            newPost.Authors.Add(new AtomPerson());
            newPost.Authors[0].Name = Properties.Settings.Default.blogAuthName;
            newPost.Authors[0].Email = userName;


            Uri queryUri = new Uri("http://www.blogger.com/feeds/" + 
                Properties.Settings.Default.blogID + "/posts/default");

            Console.WriteLine(newPost.Published + "\n" +newPost.Content.Content);
            try
            {
                AtomEntry createdEntry = service.Insert(queryUri, newPost);
            }
            catch (Exception ex)
            {
                statusLabel.Text = "Error: entry could not be posted to blag.";
                return;
            }


            statusLabel.Text = "Done.";
            
            /*SmtpClient mailClient = new SmtpClient("smtp.gmail.com", 587);

            mailClient.EnableSsl = true;

            NetworkCredential cred = new NetworkCredential(

                "snietfeld",

                "j814fngi95jkj");

            mailClient.Credentials = cred;

            

            mailClient.Send("snietfeld@gmail.com", "snietfeld1.blag@blogger.com",

                "", richTextBox1.Text);*/

        }

        public static string insertHTMLCodes(string inputString)
        {
            inputString = inputString.Replace("&", "&amp;");
            inputString = inputString.Replace("<", "&lt;");
            inputString = inputString.Replace(">", "&gt;");

            return inputString;
        }

        private void newLabelBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (selectedEntry == null) return;

            if (e.KeyChar == 13 && !currentCodex.getAllLabels().Contains(newLabelBox.Text))
            {
                debug();
                selectedEntry.addLabel(newLabelBox.Text);
                debug();
                refreshLabelList();
                newLabelBox.Clear();
            }   
        }

        public void debug()
        {
            Console.WriteLine("");
            foreach (Entry tempEntry in currentCodex.entryList)
            {
                Console.Write(tempEntry.getEntryDate().ToString() + " : ");

                foreach (String tempLabel in tempEntry.getLabelList())
                {
                    Console.WriteLine(tempLabel.ToString());
                }
            }
            Console.WriteLine("");
        }

        private void newTagBox_Click(object sender, EventArgs e)
        {
            newLabelBox.Clear();
        }


        private void tagListBox_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            //This shouldn't be needed, as the control should already be disabled for
            //all non-entry nodes
            //if (!treeView1.SelectedNode.Name.StartsWith("#entry") ||
                //selectedEntry == null) return;

            if (e.NewValue == CheckState.Checked)
            {
                if(!selectedEntry.hasLabel(tagListBox.Items[e.Index].ToString()))
                    selectedEntry.addLabel(tagListBox.Items[e.Index].ToString());
            }
            else
            {
                if (selectedEntry.hasLabel(tagListBox.Items[e.Index].ToString()))
                    selectedEntry.removeLabel(tagListBox.Items[e.Index].ToString());
            }
        }

        private void forceEditToolStripMenuItem_Click(object sender, EventArgs e)
        {
            entryTextBox.ReadOnly = false;
        }

        private void toolStripMenuItem3_Click(object sender, EventArgs e)
        {
            if (tagListBox.SelectedItem == null) return;

            if (MessageBox.Show("The selected tag will be removed from all entries. Groovy?",
                "Confirm delete", MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                currentCodex.deleteAllOccurrencesOfLabel(tagListBox.SelectedItem.ToString());
                refreshLabelList();
            }
            else return;
        }

        private void tagListBox_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                Point p = new Point(e.X, e.Y);
                tagListBox.SelectedIndex = tagListBox.IndexFromPoint(p);
            }
        }

        private void toolStripTextBox1_KeyDown(object sender, KeyEventArgs e)
        {
            if (tagListBox.SelectedItem == null) return;

            if (e.KeyValue == 13)
            {
                Console.Out.WriteLine("enter pressed...");
                currentCodex.renameAllOccurrencesOfTag(
                    tagListBox.SelectedItem.ToString(), toolStripTextBox1.Text);

                refreshLabelList();
                tagsContextMenu.Close();
                toolStripTextBox1.Text = "Rename as...";
            }
        }

        private void toolStripTextBox1_Click(object sender, EventArgs e)
        {
            toolStripTextBox1.Clear();
        }

        private void CodexGUI_SizeChanged(object sender, EventArgs e)
        {
            Properties.Settings.Default.formWidth = this.Width;
            Properties.Settings.Default.formHeight = this.Height;
            Properties.Settings.Default.Save();
        }

        private void CodexGUI_LocationChanged(object sender, EventArgs e)
        {
            Properties.Settings.Default.formLocation = this.Location;
            Properties.Settings.Default.Save();
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            entryTextBox.Copy();
        }

        private void cutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            entryTextBox.Cut();
        }

        private void newFieldTextBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if(selectedEntry == null) return;

            //If ENTER pressed...
            if (e.KeyChar == 13 && !newFieldTextBox.Text.Equals(""))
            {
                foreach (Entry tempEntry in currentCodex.entryList)
                {
                    tempEntry.addField(newFieldTextBox.Text);
                }

                refreshFieldGrid();

                newFieldTextBox.Text = "New field...";
            }
        }

        private void refreshFieldGrid()
        {
            fieldNameCol.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
            int newRowIndex;

            
            //Get selected cells
            DataGridViewSelectedCellCollection selectedCells = null;
            if (fieldGrid.SelectedCells != null)
                selectedCells = fieldGrid.SelectedCells;

           
            //Clear grid
            fieldGrid.Rows.Clear();

            
            //Remove empty labels
            if(selectedEntry != null)
                selectedEntry.removeBlankTags();

            Console.WriteLine("AllFields Count: " + currentCodex.getAllFieldNames().Count);
            //Get all tags used in codex and add to grid
            foreach (string tempFieldName in currentCodex.getAllFieldNames())
            {
                newRowIndex = fieldGrid.NewRowIndex;
                Console.WriteLine("Adding row: " + tempFieldName);
                fieldGrid.Rows.Add(1);
                Console.WriteLine("Rowcount: " + fieldGrid.Rows.Count + "\nNewRowIndex: " + newRowIndex);
                Console.WriteLine("Setting row: " + newRowIndex + " to " + tempFieldName);
                fieldGrid.Rows[newRowIndex].Cells[0].Value = tempFieldName;
            }

            //Fill in field values
            if (selectedEntry != null)
            {
                foreach (DataGridViewRow tempRow in fieldGrid.Rows)
                {
                    string fieldName = (string)tempRow.Cells[0].Value;

                    tempRow.Cells[1].Value = selectedEntry.getFieldValue(fieldName);
                }

                //fieldGrid.ClearSelection();
            }


            //foreach (DataGridViewCell tempCell in selectedCells)
            //{ tempCell.Selected = true; }
            try
            {
                Console.WriteLine("Entry fields: ");
                foreach (FieldTag tempField in selectedEntry.getFieldList())
                {
                    Console.WriteLine(tempField.ToString());
                }
            }
            catch (Exception ex) { }
        }



        private void fieldGrid_CellValueChanged(object sender, EventArgs e)
        {
            commitFieldCellChanges();
        }

        private void commitFieldCellChanges()
        {
            try
            {
                if (fieldGrid.CurrentCell.Value.ToString().Equals("")) return;

                DataGridViewRow row = fieldGrid.Rows[fieldGrid.CurrentCell.RowIndex];

                if (fieldGrid.SelectedCells[0].IsInEditMode)
                {
                    selectedEntry.setFieldValue(row.Cells[0].Value.ToString(), row.Cells[1].Value.ToString());
                }
            }
            catch (Exception ex) { }
        }

        private void newFieldTextBox_Click(object sender, EventArgs e)
        {
            newFieldTextBox.Clear();
        }

        private void CodexGUI_Resize(object sender, EventArgs e)
        {
            Properties.Settings.Default.formHeight = this.Height;
            Properties.Settings.Default.formWidth = this.Width;
            Console.WriteLine("New height: " + this.Height + "x" + this.Width);
        }

        private void CodexGUI_Move(object sender, EventArgs e)
        {
            Properties.Settings.Default.formLocation = this.Location;
        }
    }
}